# author: hulingchuan@hotmail.com
#
# Connector
# connect to remote server and execute directives

require 'net/https'
require_relative './logger_singleton'
require 'openssl'
require 'json'

class Connector

  PLAYER_ID_KEY   = 'playerId'
  ACTION_KEY      = 'action'
  SESSION_ID_KEY  = 'sessionId'
  DATA_KEY        = 'data'
  WORD_KEY        = 'word'
  NUM_OF_WORD_KEY = 'numberOfWordsToGuess'
  GUESS_KEY       = 'guess'
  TRY_LIMIT_KEY   = 'numberOfGuessAllowedForEachWord'
  SCORE_KEY       = 'score'
  MESSAGE_KEY     = 'message'
  CORRECT_KEY     = 'correctWordCount'

  START_GAME_ACTION = 'startGame'
  NEXT_WORD_ACTION  = 'nextWord'
  GUESS_WORD_ACTION = 'guessWord'
  GET_RESULT_ACTION = 'getResult'
  SUBMIT_ACTION     = 'submitResult'

  public
  def initialize (url)
    encoded_url = URI.encode url
    @uri        = URI.parse(encoded_url)
    @logger     = LoggerSingleton.instance

    @https = Net::HTTP.new(@uri.host,@uri.port)
    @https.use_ssl = true
    @req = Net::HTTP::Post.new(
        @uri.path,
        initheader = {'Content-Type' =>'application/json'}
    )

    @logger.info 'initialized connector'
  end

  public
  def start_game (id)
    @logger.info 'stating game'
    data = {
        PLAYER_ID_KEY => id,
        ACTION_KEY    => START_GAME_ACTION,
    }
    res = request data
    @session_id  = res[SESSION_ID_KEY]
    @num_of_word = res[DATA_KEY][NUM_OF_WORD_KEY]

    @logger.info res[MESSAGE_KEY]

    res[DATA_KEY][TRY_LIMIT_KEY]
  end

  def has_next_word
    @num_of_word > 0
  end

  def next_word
    @logger.info 'getting next word'
    @logger.info  "#{@num_of_word } words left"
    data = {
      SESSION_ID_KEY => @session_id,
      ACTION_KEY     => NEXT_WORD_ACTION,
    }

    res = request data
    @num_of_word -= 1

    res[DATA_KEY][WORD_KEY]
  end

  def guess_word (c)

    data = {
      SESSION_ID_KEY => @session_id,
      ACTION_KEY     => GUESS_WORD_ACTION,
      GUESS_KEY      => c,
    }

    res = request data

    res[DATA_KEY][WORD_KEY]
  end

  def get_result

    @logger.info 'fetching result'

    data = {
        SESSION_ID_KEY => @session_id,
        ACTION_KEY     => GET_RESULT_ACTION,
    }

    res = request data

    @logger.info "score: #{res[DATA_KEY][SCORE_KEY]}"
    @logger.info "correct: #{res[DATA_KEY][CORRECT_KEY]}"
  end

  def submit

    data = {
        SESSION_ID_KEY => @session_id,
        ACTION_KEY     => SUBMIT_ACTION,
    }

    res = request data

    @logger.info res[MESSAGE_KEY]
  end

  private
  def request (data)

    @req.body = data.to_json

    success = nil
    while success.nil?
      begin
        res = @https.start { |http|
          http.request(@req)
        }
        success = true
      rescue
        @logger.info 'request fail, retrying...'
      end
    end

    JSON.parse res.body
  end

end